package com.shangxian.giveithome.service.impl;


import cn.hutool.core.codec.Base64;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.shangxian.giveithome.code.AuthCode;
import com.shangxian.giveithome.entity.UserInfo;
import com.shangxian.giveithome.entity.WxInfo;
import com.shangxian.giveithome.entity.WxLogin;
import com.shangxian.giveithome.exception.ExceptionUtils;
import com.shangxian.giveithome.service.ApiService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.spec.AlgorithmParameterSpec;

import static com.shangxian.giveithome.code.AuthCode.ACCESS_TOKEN_ERROR;
import static com.shangxian.giveithome.config.SettingConfig.AppId;
import static com.shangxian.giveithome.config.SettingConfig.Secret;

/**
 * @author Administrator
 */
@Service
@Slf4j
public class ApiServiceImpl implements ApiService {


    @Autowired
    private RestTemplate restTemplate;


    /**
     * 获取session_key
     *
     * @param code
     * @return
     */
    @Override
    public WxInfo getSession(String code) {
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" +
                AppId + "&secret=" + Secret + "&js_code=" + code + "&grant_type=authorization_code";
        ResponseEntity<String> forEntity = restTemplate.getForEntity(url, String.class);
        String body = forEntity.getBody();
        if (body == null) {
            ExceptionUtils.error(AuthCode.OPEN_ID_ERROR);
        }
        ObjectMapper objectMapper = new ObjectMapper();
        WxInfo wxInfo = null;
        try {
            wxInfo = objectMapper.readValue(body, WxInfo.class);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return wxInfo;
    }

    /**
     * 获取手机号码
     *
     * @param wxLogin
     * @param session_key
     * @return
     */
    @Override
    public UserInfo getDetails(WxLogin wxLogin, String session_key) {
        UserInfo userInfo = new UserInfo();
        try {
            userInfo.setPhone(decryptData(wxLogin.getEncryptedData(), session_key, wxLogin.getIv()));
            return userInfo;
            //可以在此进行授权拦截，利用手机号禁用用户的授权
        } catch (Exception e) {
            //ExceptionUtils.error(AuthCode.PHONE_ERROR);
            log.error("手机号码获取失败");
        }
        return userInfo;
    }

    /**
     * 获取access_token
     * @return
     */
    @Override
    public String getAccessToken() {
        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" +
                AppId + "&secret=" + Secret;
        String jsonStr = restTemplate.getForObject(url, String.class);
        JSONObject json = JSONObject.parseObject(jsonStr);
        String access_token = json.getString("access_token");
        if (access_token == null) {
            ExceptionUtils.error(ACCESS_TOKEN_ERROR);
            log.error("access_token获取失败");
        }
        return access_token;
    }

    public static String decryptData(String encryptedData, String sessionKey, String iv) throws Exception {
        byte[] encData = Base64.decode(encryptedData);
        byte[] ivs = Base64.decode(iv);
        byte[] key = Base64.decode(sessionKey);

        AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivs);
        //调用AES/DES加密算法包最精要的就是下面两句话对称加密
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
        return JSON.parseObject(new String(cipher.doFinal(encData), "UTF-8")).getString("purePhoneNumber");
    }

}
